prepare-root: Move root.transient parsing rootfs parsing
authorColin Walters <walters@verbum.org>
Wed, 16 Jul 2025 17:18:58 +0000 (13:18 -0400)
committerColin Walters <walters@verbum.org>
Wed, 16 Jul 2025 17:30:33 +0000 (13:30 -0400)
This deduplicates more code between main boot and soft reboot,
and is prep for supporting `rootfs.transient-ro = true`.

src/libostree/ostree-soft-reboot.c
src/libotcore/otcore-prepare-root.c
src/libotcore/otcore.h
src/switchroot/ostree-prepare-root.c

index 7ed7e067ade9b44474d77930b656d791db20e643..a94ab41ff852e06a35b83a3d17f874f7297f1b56 100644 (file)
@@ -35,9 +35,7 @@
 #include "otcore.h"
 
 /* This key configures the / mount in the deployment root */
-#define ROOT_KEY "root"
 #define ETC_KEY "etc"
-#define TRANSIENT_KEY "transient"
 
 gboolean
 _ostree_prepare_soft_reboot (GError **error)
@@ -50,11 +48,6 @@ _ostree_prepare_soft_reboot (GError **error)
   if (!config)
     return FALSE;
 
-  gboolean root_transient = FALSE;
-  if (!ot_keyfile_get_boolean_with_default (config, ROOT_KEY, TRANSIENT_KEY, FALSE, &root_transient,
-                                            error))
-    return FALSE;
-
   g_autofree char *kernel_cmdline = read_proc_cmdline ();
   g_autoptr (RootConfig) rootfs_config
       = otcore_load_rootfs_config (kernel_cmdline, config, TRUE, error);
@@ -72,8 +65,8 @@ _ostree_prepare_soft_reboot (GError **error)
 
   // Tracks if we did successfully enable it at runtime
   bool using_composefs = false;
-  if (!otcore_mount_rootfs (rootfs_config, &metadata_builder, root_transient, sysroot_path,
-                            target_deployment, OTCORE_RUN_NEXTROOT, &using_composefs, error))
+  if (!otcore_mount_rootfs (rootfs_config, &metadata_builder, sysroot_path, target_deployment,
+                            OTCORE_RUN_NEXTROOT, &using_composefs, error))
     return glnx_prefix_error (error, "failed to mount composefs");
 
   if (!using_composefs)
index df5d3b0db2df09ffbde616a7cd6f62f011872342..a52d711d26aa8cf5b8c1c480e3e100a3f8de1005 100644 (file)
@@ -35,6 +35,8 @@
 #define BINDING_KEYPATH "/etc/ostree/initramfs-root-binding.key"
 // The kernel argument to configure composefs
 #define CMDLINE_KEY_COMPOSEFS "ostree.prepare-root.composefs"
+/* This key configures the / mount in the deployment root */
+#define ROOT_KEY "root"
 // The key in the config for etc
 #define ETC_KEY "etc"
 
@@ -184,6 +186,10 @@ otcore_load_rootfs_config (const char *cmdline, GKeyFile *config, gboolean load_
 
   g_autoptr (RootConfig) ret = g_new0 (RootConfig, 1);
 
+  if (!ot_keyfile_get_boolean_with_default (config, ROOT_KEY, OTCORE_PREPARE_ROOT_TRANSIENT_KEY,
+                                            FALSE, &ret->root_transient, error))
+    return NULL;
+
   g_autofree char *enabled = g_key_file_get_value (config, OTCORE_PREPARE_ROOT_COMPOSEFS_KEY,
                                                    OTCORE_PREPARE_ROOT_ENABLED_KEY, NULL);
   if (g_strcmp0 (enabled, "signed") == 0)
@@ -429,8 +435,8 @@ otcore_mount_etc (GKeyFile *config, GVariantBuilder *metadata_builder, const cha
 
 gboolean
 otcore_mount_rootfs (RootConfig *rootfs_config, GVariantBuilder *metadata_builder,
-                     gboolean root_transient, const char *root_mountpoint, const char *deploy_path,
-                     const char *mount_target, bool *out_using_composefs, GError **error)
+                     const char *root_mountpoint, const char *deploy_path, const char *mount_target,
+                     bool *out_using_composefs, GError **error)
 {
   struct stat stbuf;
   /* Record the underlying plain deployment directory (device,inode) pair
@@ -444,7 +450,7 @@ otcore_mount_rootfs (RootConfig *rootfs_config, GVariantBuilder *metadata_builde
 
   /* Pass on the state  */
   g_variant_builder_add (metadata_builder, "{sv}", OTCORE_RUN_BOOTED_KEY_ROOT_TRANSIENT,
-                         g_variant_new_boolean (root_transient));
+                         g_variant_new_boolean (rootfs_config->root_transient));
 
   bool using_composefs = FALSE;
 #ifdef HAVE_COMPOSEFS
@@ -472,12 +478,16 @@ otcore_mount_rootfs (RootConfig *rootfs_config, GVariantBuilder *metadata_builde
   // https://github.com/systemd/systemd/blob/604b2001081adcbd64ee1fbe7de7a6d77c5209fe/src/basic/mountpoint-util.h#L36
   // which bumps up these defaults for the rootfs a bit.
   g_autofree char *root_upperdir
-      = root_transient ? g_build_filename (OTCORE_RUN_OSTREE_PRIVATE, "root/upper", NULL) : NULL;
+      = rootfs_config->root_transient
+            ? g_build_filename (OTCORE_RUN_OSTREE_PRIVATE, "root/upper", NULL)
+            : NULL;
   g_autofree char *root_workdir
-      = root_transient ? g_build_filename (OTCORE_RUN_OSTREE_PRIVATE, "root/work", NULL) : NULL;
+      = rootfs_config->root_transient
+            ? g_build_filename (OTCORE_RUN_OSTREE_PRIVATE, "root/work", NULL)
+            : NULL;
 
   // Propagate these options for transient root, if provided
-  if (root_transient)
+  if (rootfs_config->root_transient)
     {
       if (!glnx_shutil_mkdir_p_at (AT_FDCWD, root_upperdir, 0755, NULL, error))
         return glnx_prefix_error (error, "Failed to create %s", root_upperdir);
index 47aa751b54a0da457d7603956bd1199ea1f6af24..456db9d67f4aa695c20ec443ae55cdf4752328b3 100644 (file)
@@ -67,6 +67,7 @@ GKeyFile *otcore_load_config (int rootfs, const char *filename, GError **error);
 typedef struct
 {
   OtTristate composefs_enabled;
+  gboolean root_transient;
   gboolean require_verity;
   gboolean is_signed;
   char *signature_pubkey;
@@ -95,9 +96,8 @@ RootConfig *otcore_load_rootfs_config (const char *cmdline, GKeyFile *config, gb
  * Returns: %TRUE on success, %FALSE on error.
  */
 gboolean otcore_mount_rootfs (RootConfig *rootfs_config, GVariantBuilder *metadata_builder,
-                              gboolean root_transient, const char *root_mountpoint,
-                              const char *deploy_path, const char *mount_target,
-                              bool *out_using_composefs, GError **error);
+                              const char *root_mountpoint, const char *deploy_path,
+                              const char *mount_target, bool *out_using_composefs, GError **error);
 
 gboolean otcore_mount_etc (GKeyFile *config, GVariantBuilder *metadata_builder,
                            const char *mount_target, GError **error);
index b00117998c7e50dd22178386d7f0b3c27f385781..cf3bd1c940b538f25feb26abfe9e083e9b742e35 100644 (file)
@@ -79,9 +79,6 @@
 #define SYSROOT_KEY "sysroot"
 #define READONLY_KEY "readonly"
 
-/* This key configures the / mount in the deployment root */
-#define ROOT_KEY "root"
-
 #define OSTREE_PREPARE_ROOT_DEPLOYMENT_MSG \
   SD_ID128_MAKE (71, 70, 33, 6a, 73, ba, 46, 01, ba, d3, 1a, f8, 88, aa, 0d, f7)
 
@@ -184,11 +181,6 @@ main (int argc, char *argv[])
     errx (EXIT_FAILURE, "Failed to parse config: %s", error->message);
 
   gboolean sysroot_readonly = FALSE;
-  gboolean root_transient = FALSE;
-
-  if (!ot_keyfile_get_boolean_with_default (config, ROOT_KEY, OTCORE_PREPARE_ROOT_TRANSIENT_KEY,
-                                            FALSE, &root_transient, &error))
-    return FALSE;
 
   // We always parse the composefs config, because we want to detect and error
   // out if it's enabled, but not supported at compile time.
@@ -263,13 +255,13 @@ main (int argc, char *argv[])
 
   // Tracks if we did successfully enable it at runtime
   bool using_composefs = false;
-  if (!otcore_mount_rootfs (rootfs_config, &metadata_builder, root_transient, root_mountpoint,
-                            deploy_path, TMP_SYSROOT, &using_composefs, &error))
+  if (!otcore_mount_rootfs (rootfs_config, &metadata_builder, root_mountpoint, deploy_path,
+                            TMP_SYSROOT, &using_composefs, &error))
     errx (EXIT_FAILURE, "Failed to mount composefs: %s", error->message);
 
   if (!using_composefs)
     {
-      if (root_transient)
+      if (rootfs_config->root_transient)
         {
           errx (EXIT_FAILURE, "Must enable composefs with root.transient");
         }
@@ -302,7 +294,7 @@ main (int argc, char *argv[])
   /* Prepare /etc.
    * No action required if sysroot is writable. Otherwise, a bind-mount for
    * the deployment needs to be created and remounted as read/write. */
-  if (sysroot_readonly || using_composefs || root_transient)
+  if (sysroot_readonly || using_composefs || rootfs_config->root_transient)
     {
       if (!otcore_mount_etc (config, &metadata_builder, TMP_SYSROOT, &error))
         errx (EXIT_FAILURE, "Failed to mount etc: %s", error->message);